﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
using System.Windows.Forms;
using System.Drawing.Drawing2D;
using Microsoft.Win32;

namespace eTMS.Controls
{
    public class Button : System.Windows.Forms.Button
    {
        public Button()
        {
            SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.OptimizedDoubleBuffer, true);
            this.BackColor = Color.FromArgb(255, 255, 255);
            this.bgColor = Color.RoyalBlue;
            this.BorderColor = Color.SteelBlue;
            this.StartGradientColor = Color.FromArgb(220, 220, 255);// Color.FromArgb(150, 80, 180, 226);
            this.EndGradientColor = Color.FromArgb(200, 111, 167, 217);
            this.HoverStartColor = Color.FromArgb(100, 252, 239, 220);
            this.HoverEndColor = Color.FromArgb(200, 252, 174, 63);
            this.MouseDownStartColor = Color.FromArgb(252, 200, 150);//Color.FromArgb(100,209,221,237);
            this.MouseDownEndColor = Color.FromArgb(252, 174, 63);//Color.FromArgb(200,136,173,248);
            this.startgradColor = this.deactivestartColor;
            this.endgradColor = this.deactiveendColor;
            OnSizeChanged(new EventArgs());
        }
        private bool hover = false;
        private Color deactivestartColor;
        private Color deactiveendColor;
        private Color hoverstartColor;
        private Color hoverendColor;
        private Color mousedownstartColor;
        private Color mousedownendColor;
        private Color bgColor;
        public Color BorderColor
        {
            get
            {
                return bgColor;
            }
            set
            {
                bgColor = value;
            }
        }
        public Color HoverStartColor
        {
            get
            {
                return hoverstartColor;
            }
            set
            {
                hoverstartColor = value;
            }
        }
        public Color HoverEndColor
        {
            get
            {
                return hoverendColor;
            }
            set
            {
                hoverendColor = value;
            }
        }
        public Color MouseDownStartColor
        {
            get
            {
                return mousedownstartColor;
            }
            set
            {
                mousedownstartColor = value;
            }
        }
        public Color MouseDownEndColor
        {
            get
            {
                return mousedownendColor;
            }
            set
            {
                mousedownendColor = value;
            }
        }
        private int roundPercent = 30;
        public int RoundPercent
        {
            get
            {
                return roundPercent;
            }
            set
            {
                roundPercent = value;
            }
        }
        private GraphicsPath GetRoundPath()
        {
            GraphicsPath gph = new GraphicsPath();
            Rectangle rc = this.ClientRectangle;
            if (roundPercent <= 0)
            {
                gph.AddRectangle(rc);
            }
            else
            {
                int R = Math.Min(rc.Width, rc.Height) * roundPercent / 100;
                gph.AddArc(0, 0, R, R, 180, 90);
                gph.AddLine(rc.Left + R / 2, rc.Top, rc.Left + rc.Width - R / 2, rc.Top);
                gph.AddArc(rc.Left + rc.Width - R - 1, rc.Top, R, R, 270, 90);
                gph.AddLine(rc.Left + rc.Width - 1, rc.Top + R / 2, rc.Left + rc.Width - 1, rc.Top + rc.Height - R / 2);
                gph.AddArc(rc.Left + rc.Width - R - 1, rc.Top - R + rc.Height - 1, R, R, 0, 90);
                gph.AddLine(rc.Left + rc.Width - R / 2, rc.Top + rc.Height - 1, rc.Left + R / 2, rc.Top + rc.Height - 1);
                gph.AddArc(rc.Left, rc.Top - R + rc.Height - 1, R, R, 90, 90);
                gph.AddLine(rc.Left, rc.Top + rc.Height - R / 2, rc.Left, rc.Top + R / 2);
            }
            return gph;
        }
        private GraphicsPath GetRoundPathRegion()
        {
            GraphicsPath gph = new GraphicsPath();
            Rectangle rc = this.ClientRectangle;
            if (roundPercent <= 0)
            {
                gph.AddRectangle(rc);
            }
            else
            {
                int R = Math.Min(rc.Width, rc.Height) * roundPercent / 100;
                gph.AddArc(0, 0, R, R, 180, 90);
                gph.AddLine(rc.Left + R / 2, rc.Top, rc.Left + rc.Width - R / 2, rc.Top);
                gph.AddArc(rc.Left + rc.Width - R, rc.Top, R, R, 270, 90);
                gph.AddLine(rc.Left + rc.Width, rc.Top + R / 2, rc.Left + rc.Width, rc.Top + rc.Height - R / 2);
                gph.AddArc(rc.Left + rc.Width - R, rc.Top - R + rc.Height, R, R, 0, 90);
                gph.AddLine(rc.Left + rc.Width - R / 2, rc.Top + rc.Height, rc.Left + R / 2, rc.Top + rc.Height);
                gph.AddArc(rc.Left, rc.Top - R + rc.Height, R, R, 90, 90);
                gph.AddLine(rc.Left, rc.Top + rc.Height - R / 2, rc.Left, rc.Top + R / 2);
            }
            return gph;
        }
        protected override void OnSizeChanged(EventArgs e)
        {
            base.OnSizeChanged(e);
            Rectangle rc = this.ClientRectangle;
            int R = Math.Min(rc.Width, rc.Height) * roundPercent / 100;
            GraphicsPath gph = GetRoundPathRegion();
            Region rg = new Region(gph);
            this.Region = rg;
            this.Invalidate();
        }
        private Color endgradColor;
        private Color startgradColor;
        private LinearGradientMode gradientMode = LinearGradientMode.Vertical;
        private float gradPercent = 0.5f;
        public LinearGradientMode GradientMode
        {
            get
            {
                return gradientMode;
            }
            set
            {
                gradientMode = value;
                this.Invalidate();
            }
        }
        public float GradientPercent
        {
            get
            {
                return gradPercent;
            }
            set
            {
                gradPercent = value;
                this.Invalidate();
            }
        }
        public Color StartGradientColor
        {
            get
            {
                return deactivestartColor;
            }
            set
            {
                deactivestartColor = value;
                this.Invalidate();
            }
        }
        public Color EndGradientColor
        {
            get
            {
                return deactiveendColor;
            }
            set
            {
                deactiveendColor = value;
                this.Invalidate();
            }
        }

        private void DrawBackGround(Graphics g)
        {
            // Create a rectangle
            //ButtonRenderer.(g, this.ClientRectangle, System.Windows.Forms.VisualStyles.PushButtonState.Default);
            g.Clear(this.BackColor);
            Rectangle rect = new Rectangle(1, 1, this.Width - 2, this.Height - 2);
            // Create a linear gradient brush
            LinearGradientBrush rgBrush =
                new LinearGradientBrush(
                rect, this.startgradColor, this.endgradColor, gradientMode
                );					// Set signma bell shape
            rgBrush.SetSigmaBellShape(gradPercent, 1.0f);
            // Fill rectangle again
            g.FillRectangle(rgBrush, rect);
            rgBrush.Dispose();
            if (this.Enabled)
            {
                Blend blend = new Blend();
                float[] factArray = { 0.0f, 0.3f, 0.8f, 1.0f };
                float[] posArray = { 0.0f, 0.4f, 0.6f, 1.0f };
                // Set Factors and Positions properties of Blend
                blend.Factors = factArray;
                blend.Positions = posArray;
                // Set smoothing mode of Graphics object
                g.SmoothingMode = SmoothingMode.AntiAlias;
                // Create path and add a rectangle
                GraphicsPath path = new GraphicsPath();
                Rectangle rc = new Rectangle(rect.X, rect.Y - rect.Height, rect.Width, 6 * rect.Height);
                path.AddEllipse(rc);
                // Create path gradient brush
                PathGradientBrush pthBrush =
                    new PathGradientBrush(path);
                // Set Blend and FocusScales properties
                pthBrush.Blend = blend;
                pthBrush.FocusScales = new PointF(0.9f, 0.2f);
                Color[] colors = { Color.FromArgb(10, this.startgradColor) };
                // Set CenterColor and SurroundColors properties
                pthBrush.CenterColor = Color.FromArgb(220, Color.White);
                pthBrush.SurroundColors = colors;
                g.FillEllipse(pthBrush, rc);
                pthBrush.Dispose();
            }
            // Dispose of object
            DrawBorder(g);


        }
        private void DrawImage(Graphics g)
        {
            if (this.Image == null)
            {
                if (this.ImageList == null)
                    return;
                if ((this.ImageList.Images.Count == 0) || (this.ImageIndex >= this.ImageList.Images.Count) || (this.ImageIndex < 0))
                    return;
                this.Image = this.ImageList.Images[this.ImageIndex];
            }
            Rectangle rc = this.ClientRectangle;
            int imagePadding = ((rc.Width - (int)g.MeasureString(this.Text, this.Font,this.Size).Width) / 2 - this.Image.Width)/2;
            if (this.ImageAlign == ContentAlignment.MiddleCenter)
            {
                rc = new Rectangle((rc.Width - this.Image.Width) / 2, (this.Height - this.Image.Height) / 2, this.Image.Width, this.Image.Height);
            }
            else if (this.ImageAlign == ContentAlignment.MiddleLeft)
            {
                rc = new Rectangle(imagePadding, (this.Height - this.Image.Height) / 2, this.Image.Width, this.Image.Height);
            }
            else if (this.ImageAlign == ContentAlignment.MiddleRight)
            {
                rc = new Rectangle(this.Width - this.Image.Width - 2, (this.Height - this.Image.Height) / 2, this.Image.Width, this.Image.Height);
            }
            else if (this.ImageAlign == ContentAlignment.BottomCenter)
            {
                rc = new Rectangle((rc.Width - this.Image.Width) / 2, this.Height - this.Image.Height, this.Image.Width, this.Image.Height);
            }
            else if (this.ImageAlign == ContentAlignment.BottomLeft)
            {
                rc = new Rectangle(imagePadding, this.Height - this.Image.Height, this.Image.Width, this.Image.Height);
            }
            else if (this.ImageAlign == ContentAlignment.BottomRight)
            {
                rc = new Rectangle(this.Width - this.Image.Width - imagePadding, this.Height - this.Image.Height, this.Image.Width, this.Image.Height);
            }
            else if (this.ImageAlign == ContentAlignment.TopCenter)
            {
                rc = new Rectangle((rc.Width - this.Image.Width) / 2, 0, this.Image.Width, this.Image.Height);
            }
            else if (this.ImageAlign == ContentAlignment.TopLeft)
            {
                rc = new Rectangle(imagePadding, this.Height - this.Image.Height, this.Image.Width, this.Image.Height);
            }
            else if (this.ImageAlign == ContentAlignment.TopRight)
            {
                rc = new Rectangle(this.Width - this.Image.Width - imagePadding, 0, this.Image.Width, this.Image.Height);
            }
            Image img = this.Image;
            g.DrawImage(img, rc);
        }

        private void DrawText(Graphics g)
        {
            Rectangle rc = this.ClientRectangle;
            SolidBrush br = null;
            StringFormat ft = new StringFormat();
            ft.HotkeyPrefix = System.Drawing.Text.HotkeyPrefix.Show;
            if (this.TextAlign == ContentAlignment.MiddleCenter)
            {
                ft.LineAlignment = StringAlignment.Center;
                ft.Alignment = StringAlignment.Center;
            }
            else if (this.TextAlign == ContentAlignment.MiddleLeft)
            {
                ft.LineAlignment = StringAlignment.Center;
                ft.Alignment = StringAlignment.Near;
            }
            else if (this.TextAlign == ContentAlignment.MiddleRight)
            {
                ft.LineAlignment = StringAlignment.Center;
                ft.Alignment = StringAlignment.Far;
            }
            else if (this.TextAlign == ContentAlignment.BottomCenter)
            {
                ft.LineAlignment = StringAlignment.Far;
                ft.Alignment = StringAlignment.Center;
            }
            else if (this.TextAlign == ContentAlignment.BottomLeft)
            {
                ft.LineAlignment = StringAlignment.Far;
                ft.Alignment = StringAlignment.Near;
            }
            else if (this.TextAlign == ContentAlignment.BottomRight)
            {
                ft.LineAlignment = StringAlignment.Far;
                ft.Alignment = StringAlignment.Far;
            }
            else if (this.TextAlign == ContentAlignment.TopCenter)
            {
                ft.LineAlignment = StringAlignment.Near;
                ft.Alignment = StringAlignment.Center;
            }
            else if (this.TextAlign == ContentAlignment.TopLeft)
            {
                ft.LineAlignment = StringAlignment.Near;
                ft.Alignment = StringAlignment.Near;
            }
            else if (this.TextAlign == ContentAlignment.TopRight)
            {
                ft.LineAlignment = StringAlignment.Near;
                ft.Alignment = StringAlignment.Far;
            }

            if (this.Enabled)
            {
                br = new SolidBrush(this.ForeColor);
            }
            else
            {
                br = new SolidBrush(SystemColors.GrayText);
            }
            g.DrawString(this.Text, this.Font, br, rc, ft);
            br.Dispose();
            ft.Dispose();
        }
        protected override void OnPaint(System.Windows.Forms.PaintEventArgs e)
        {
            base.OnPaint(e);
            DrawBackGround(e.Graphics);
            DrawImage(e.Graphics);
            DrawText(e.Graphics);
        }
        protected override void OnMouseMove(MouseEventArgs e)
        {
            base.OnMouseMove(e);
            if (!this.hover)
            {
                ChangeColor(this.hoverstartColor, this.hoverendColor);
                this.Invalidate();
                hover = true;
            }

        }
        private void ChangeColor(Color startColor, Color endColor)
        {
            this.startgradColor = startColor;
            this.endgradColor = endColor;
            this.Invalidate();

        }
        protected override void OnLostFocus(EventArgs e)
        {
            base.OnLostFocus(e);
            ChangeColor(this.deactivestartColor, this.deactiveendColor);
            hover = false;
        }
        protected override void OnMouseLeave(EventArgs e)
        {
            base.OnMouseLeave(e);
            ChangeColor(this.deactivestartColor, this.deactiveendColor);
            hover = false;
        }
        protected override void OnGotFocus(EventArgs e)
        {
            base.OnGotFocus(e);
            if (this.Enabled)
                ChangeColor(this.mousedownstartColor, this.mousedownendColor);
        }
        protected override void OnMouseDown(MouseEventArgs e)
        {
            base.OnMouseDown(e);
            ChangeColor(this.mousedownstartColor, this.mousedownendColor);


        }
        protected override void OnMouseUp(MouseEventArgs e)
        {
            base.OnMouseUp(e);
            ChangeColor(this.hoverstartColor, this.hoverendColor);
        }
        private void DrawBorder(Graphics g)
        {
            GraphicsPath gph = GetRoundPath();
            Pen p = new Pen(this.BorderColor, 1);
            g.DrawPath(p, gph);
            gph.Dispose();
            p.Dispose();
        }
        protected override void OnEnabledChanged(EventArgs e)
        {
            base.OnEnabledChanged(e);
            if (!this.Enabled)
            {
                ChangeColor(this.deactivestartColor, this.deactiveendColor);
                hover = false;
            }
        }

    }
}
